package com.lyn.yuv.util;

/**
 * created by lyn at 2021/10/21
 */
public class YuvHelper {

    private static class YuvHelperTypeClass {
        private static YuvHelper instance = new YuvHelper();
    }

    public static YuvHelper getInstance() {
        return YuvHelperTypeClass.instance;
    }

    private YuvUtil yuvUtil;

    private int width;

    private int height;

    private int dstWidth;

    private int dstHeight;

    private byte[] dstData;

    private enum MODE {
        ONE, TWO, THREE, FOUR
    }

    private enum Degree {
        DEGREE0, DEGREE90, DEGREE180, DEGREE270
    }

    private MODE mode = MODE.ONE;

    private Degree degree = Degree.DEGREE0;

    public void initialize(int width, int height, int dst_width, int dst_height) {
        yuvUtil = new YuvUtil();
        synchronized (yuvUtil) {
            yuvUtil.init(width, height, dst_width, dst_height);
            this.width = width;
            this.height = height;
            this.dstWidth = dst_width;
            this.dstHeight = dst_height;
            dstData = new byte[dst_width * dst_height * 3 / 2];
        }

    }

    public void reinitialize(int width, int height, int dst_width, int dst_height) {
        if (yuvUtil == null) {
            yuvUtil = new YuvUtil();
        }
        synchronized (yuvUtil) {
            yuvUtil.init(width, height, dst_width, dst_height);
            this.width = width;
            this.height = height;
            this.dstWidth = dst_width;
            this.dstHeight = dst_height;
            dstData = new byte[dst_width * dst_height * 3 / 2];
        }

    }


    public void setYuvUtil(YuvUtil yuvUtil) {
        this.yuvUtil = yuvUtil;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void setDstWidth(int dstWidth) {
        this.dstWidth = dstWidth;
    }

    public void setDstHeight(int dstHeight) {
        this.dstHeight = dstHeight;
    }

    public void setDstData(byte[] dstData) {
        this.dstData = dstData;
    }

    public void setMode(MODE mode) {
        this.mode = mode;
    }

    public void setDegree(Degree degree) {
        this.degree = degree;
    }

    public byte[] compressYUV(byte[] data) {
        if (yuvUtil == null) return null;
        int m = 0;
        switch (mode) {
            case TWO:
                m = 1;
                break;
            case THREE:
                m = 2;
                break;
            case FOUR:
                m = 3;
                break;
            default:
                m = 0;
                break;
        }

        yuvUtil.compressYUV(data, width, height, dstData, dstWidth, dstHeight, m, 0, false);

        return dstData;
    }

    public byte[] compressYUV(byte[] data, MODE mode) {
        if (yuvUtil == null) return null;
        int m = 0;
        switch (mode) {
            case TWO:
                m = 1;
                break;
            case THREE:
                m = 2;
                break;
            case FOUR:
                m = 3;
                break;
            default:
                m = 0;
                break;
        }

        yuvUtil.compressYUV(data, width, height, dstData, dstWidth, dstHeight, m, 0, false);

        return dstData;
    }

    public byte[] compressYUV(byte[] data, MODE mode, Degree degree) {
        if (yuvUtil == null) return null;
        int m = 0;
        switch (mode) {
            case TWO:
                m = 1;
                break;
            case THREE:
                m = 2;
                break;
            case FOUR:
                m = 3;
                break;
            default:
                m = 0;
                break;
        }
        int d = 0;
        switch (degree) {
            case DEGREE90:
                d = 90;
                break;
            case DEGREE180:
                d = 180;
                break;
            case DEGREE270:
                d = 270;
                break;
            default:
                d = 0;
                break;
        }
        yuvUtil.compressYUV(data, width, height, dstData, dstWidth, dstHeight, m, d, false);

        return dstData;
    }

    public byte[] compressYUV(byte[] data, MODE mode, Degree degree, boolean isMirror) {
        if (yuvUtil == null) return null;
        synchronized (yuvUtil){
            int m = 0;
            switch (mode) {
                case TWO:
                    m = 1;
                    break;
                case THREE:
                    m = 2;
                    break;
                case FOUR:
                    m = 3;
                    break;
                default:
                    m = 0;
                    break;
            }
            int d = 0;
            switch (degree) {
                case DEGREE90:
                    d = 90;
                    break;
                case DEGREE180:
                    d = 180;
                    break;
                case DEGREE270:
                    d = 270;
                    break;
                default:
                    d = 0;
                    break;
            }
            yuvUtil.compressYUV(data, width, height, dstData, dstWidth, dstHeight, m, d, isMirror);

            return dstData;
        }
    }

    public byte[] yuvI420ToNV21(byte[] data) {
        if (yuvUtil == null) return null;
        synchronized (yuvUtil){
            yuvUtil.yuvI420ToNV21(data, dstData, dstWidth, dstHeight);
            return dstData;
        }
    }
}
